from threading import Thread

class async(object):
    """
    Descriptor for functions. Makes them execute in a new thread.
    """
    func = None
    def __init__(self, modFunc):
        self.func = modFunc
    def __get__(self, instance, owner):
        self.owner = instance
    def __call__(self, *p, **kw):
        Thread(None, self.func, None, [self.owner] + p, kw).start()

class sync(object):
    """
    The logical opposite of async. Forces a method to be executed synchronously.
    """
    func = None
    owner = None
    def __init__(self, modFunc):
        self.func = modFunc
    def __get__(self, instance, owner):
        self.owner = instance
    def __call__(self, *p, **kw):
        self.func( *([self.owner] + p), **kw)

class AsyncClass(type):
    """
    All methods of classes of this type are executed asyncronously,
    except specials and privates.
    """
    def __new__(mcls, name, bases, dct):
        for k,v in dct.items():
            if not (k[:2] == "__" and k[-2:] == "__") and not (k.startswith("_"+name+"__")) and \
                not isinstance(v, (sync, async)) and hasattr(v, '__call__'):
                dct[k] = async(v)
        return super(AsyncClass, mcls).__new__(mcls, name, bases, dct)
    
    def __init__(cls, name, bases, dct):
        super(AsyncClass, cls).__init__(name, bases, dct)

class SyncClass(type):
    """
    Logical oppostite of AsyncClass. Just causes no additional asyncronous 
    methods to be created. That is, it's just type. Use this to prevent AsyncClass
    from turning your class into a "class thread"
    """
    pass

class classThread(object):
    """
    A convenience base class. All classes derived from this class are new-style,
    and have asynchronous methods, unless specified otherwise. Effectively, 
    whenever a derived class does anything, it does so in a new thread.
    CAUTION: Any class derived from this class should expect to have the same method
    launched multiple times in different threads, using the same 'self'.
    """
    __metaclass__ = AsyncClass